/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pl.pg.misra.rules;

import java.util.ArrayList;
import java.util.List;
import pl.pg.misra.AST.AST;
import pl.pg.misra.Interfaces.IRule;

/**
 *
 * @author Paweł
 */
public class AtMostOneBreakInLoopStatementRule extends AbstractRule implements IRule {

    @Override
    public List<String> checkRule(List<AST> asts) {
        List<AST> searchResult;
        List<AST> breakNodes;
        List<String> result = new ArrayList<>();

        for (AST node : asts) {
            searchResult = new ArrayList<>();

            searchResult = findNodesByType("ForStmt", node, searchResult);
            searchResult = findNodesByType("WhileStmt", node, searchResult);
            searchResult = findNodesByType("DoStmt", node, searchResult);

            for (AST loopNode : searchResult) {
                breakNodes = new ArrayList<>();

                breakNodes = findBreakNodesInLoop(loopNode, breakNodes, true);
                
                if (breakNodes.size() > 1){
                    result.add(buildViolationMessage(node, "14.6", "multiple break statements within loop"));
                }
            }
        }

        return result;
    }

    private List<AST> findBreakNodesInLoop(AST node, List<AST> result, boolean isRoot) {
        if (isRoot) {
            List<AST> children = node.getChildrens();
            
            for (AST child : children){
                result = findBreakNodesInLoop(child, result, false);
            }    
        } else {
            if (!(node.getNodeType().equals("ForStmt") || node.getNodeType().equals("WhileStmt") || node.getNodeType().equals("DoStmt"))){
                if (node.getNodeType().equals("BreakStmt")){
                    result.add(node);
                }
                else{
                    List<AST> children = node.getChildrens();
                    
                    for (AST child : children){
                        result = findBreakNodesInLoop(child, result, false);
                    }
                }
            }
        }

        return result;
    }
}
